09. Using sessions in controllers
Using sessions in controllers Heading
Using sessions in controllers
ND004 C01 L05 10 Using Sessions In Controllers
Takeaways
- Commits can succeed or fail. On fail, we want to rollback the session to avoid potential implicit commits done by the database on closing a connection.
- Good practice is to close connections at the end of every session used in a controller, to return the connection back to the connection pool.
Pattern (try-except-finally)
import sys
try:
todo = Todo(description=description)
db.session.add(todo)
db.session.commit()
except:
db.session.rollback()
error=True
print(sys.exc_info())
finally:
db.session.close()
Implementing
try
…
except
…
finally
in the app
ND004 C01 L05 10.1 Using Sessions In Controllers
Video Correction Notes
The route handler should always return something or raise an intentional exception, in the case of an error. To fix this with a simple solution, we can simply import
abort
from Flask:
from flask import abort
and we can call
abort(<status code>)
, e.g. with status code 500,
abort(500)
to rise an HTTPException for an Internal Server Error, in order to abort a request and prevent it from expecting a returned result. Since this is a course on web data modeling, we won't be going into errors in depth, but you can check out resources below.
Resources on Error Handling
Code (with corrections)
from flask import Flask, render_template, abort
# ...
@app.route('/todos/create', method=['POST'])
def create_todo():
error = False
body = {}
try:
description = request.form.get_json()['description']
todo = Todo(description=description)
db.session.add(todo)
db.session.commit()
body['description'] = todo.description
except:
error = True
db.session.rollback()
print(sys.exc_info())
finally:
db.session.close()
if error:
abort (400)
else:
return jsonify(body)
Creating an error
ND004 C01 L05 10.2 Using Sessions In Controllers
Practice
Implement this try-except-finally pattern in our create todo item route handler.
Starter Code
app.py
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgres://udacitystudios@localhost:5432/todoapp'
db = SQLAlchemy(app)
class Todo(db.Model):
__tablename__ = 'todos'
id = db.Column(db.Integer, primary_key=True)
description = db.Column(db.String(), nullable=False)
def __repr__(self):
return f'<Todo {self.id} {self.description}>'
db.create_all()
@app.route('/todos/create', method=['POST'])
def create_todo():
description = request.form.get_json()['description']
todo = Todo(description=description)
db.session.add(todo)
db.session.commit()
return jsonify({
'description': todo.description
})
@app.route('/')
def index():
return render_template('index.html', data=Todo.query.all())
templates/index.html
<html>
<head>
<title>Todo App</title>
<style>
#error {
display: none;
}
</style>
</head>
<body>
<div id="error" class="hidden">Something went wrong!</div>
<form id="form" method="post" action="/todos/create">
<input type="text" id="description" name="description" />
<input type="submit" value="Create" />
</form>
<ul id="todos">
{% for d in data %}
<li>{{ d.description }}</li>
{% endfor %}
</ul>
<script>
const descInput = document.getElementById('description');
document.getElementById('form').onsubmit = function(e) {
e.preventDefault();
const desc = descInput.value;
descInput.value = '';
fetch('/todos/create', {
method: 'POST',
body: JSON.stringify({
'description': desc,
}),
headers: {
'Content-Type': 'application/json',
}
})
.then(response => response.json())
.then(jsonResponse => {
console.log('response', jsonResponse);
li = document.createElement('li');
li.innerText = desc;
document.getElementById('todos').appendChild(li);
document.getElementById('error').className = 'hidden';
})
.catch(function() {
document.getElementById('error').className = '';
})
}
</script>
</body>
</html>
Workspace
This section contains either a workspace (it can be a Jupyter Notebook workspace or an online code editor work space, etc.) and it cannot be automatically downloaded to be generated here. Please access the classroom with your account and manually download the workspace to your local machine. Note that for some courses, Udacity upload the workspace files onto https://github.com/udacity , so you may be able to download them there.
Workspace Information:
- Default file path:
- Workspace type: jupyter-lab
- Opened files (when workspace is loaded): n/a